package cn.snmp.mutual.org.opennms.protocols.icmp;

import java.util.*;

import cn.snmp.mutual.org.opennms.protocols.exceptions.InsufficientDataException;
import cn.snmp.mutual.org.opennms.protocols.ip.OC16ChecksumProducer;


public final class TimestampRequest extends ICMPHeader {
    private int m_origStamp;

    public TimestampRequest() {
        super((byte) 13, (byte) 0);
        this.m_origStamp = (int) (new Date().getTime() & -1L);
    }

    public TimestampRequest(final byte[] buf, final int offset) {
        this.loadFromBuffer(buf, offset);
    }

    @Override
    public void computeChecksum() {
        final OC16ChecksumProducer summer = new OC16ChecksumProducer();
        super.computeChecksum(summer);
        summer.add(this.m_origStamp);
        summer.add(0);
        summer.add(0);
        this.setChecksum(summer.getChecksum());
    }

    public int storeToBuffer(final byte[] buf, int offset) {
        if (buf.length < offset + 20) {
            throw new ArrayIndexOutOfBoundsException("Array index overflow in buffer build");
        }
        this.computeChecksum();
        offset = this.storeToBuffer(buf, offset);
        buf[offset++] = (byte) (this.m_origStamp >> 24 & 0xFF);
        buf[offset++] = (byte) (this.m_origStamp >> 16 & 0xFF);
        buf[offset++] = (byte) (this.m_origStamp >> 8 & 0xFF);
        buf[offset++] = (byte) (this.m_origStamp & 0xFF);
        for (int x = 0; x < 8; ++x) {
            buf[offset++] = 0;
        }
        return offset;
    }

    public int loadFromBuffer(final byte[] buf, int offset) {
        if (buf.length < offset + 20) {
            throw new InsufficientDataException("Insufficient data to load ICMP header");
        }
        offset = super.loadFromBuffer(buf, offset);
        if (this.getType() != 13) {
            throw new IllegalArgumentException("The buffer did not contain an Timestamp Request");
        }
        this.m_origStamp = (ICMPHeader.byteToInt(buf[offset++]) << 24 | ICMPHeader.byteToInt(buf[offset++]) << 16 | ICMPHeader.byteToInt(buf[offset++]) << 8 | ICMPHeader.byteToInt(buf[offset++]));
        offset += 8;
        return offset;
    }

    public void setOriginateTS() {
        this.m_origStamp = (int) (new Date().getTime() & -1L);
    }

    public void setOriginateTS(final int ts) {
        this.m_origStamp = ts;
    }

    public int getOriginateTS() {
        return this.m_origStamp;
    }

    @Override
    public byte[] toBytes() {
        final byte[] b = new byte[20];
        this.storeToBuffer(b, 0);
        return b;
    }
}
